package org.eiahe.hr.attendance.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.eiahe.hr.attendance.domain.AnnualLeave;
import org.eiahe.hr.attendance.domain.MonthlyAttendanceStat;
import org.eiahe.hr.attendance.domain.MonthlyOvertimeStat;
import org.eiahe.hr.attendance.domain.vo.EmployeeAttendanceSummaryVo;
import org.eiahe.hr.attendance.mapper.MonthlyAttendanceStatMapper;
import org.eiahe.hr.attendance.mapper.MonthlyOvertimeStatMapper;
import org.eiahe.hr.attendance.mapper.AnnualLeaveMapper;
import org.eiahe.hr.attendance.service.IEmployeeAttendanceSummaryService;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.system.domain.HrEmployee;
import org.ehe.system.mapper.HrEmployeeMapper;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.Calendar;
import java.util.stream.Collectors;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 员工考勤汇总Service业务层处理
 *
 * @author zhangnn
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class EmployeeAttendanceSummaryServiceImpl implements IEmployeeAttendanceSummaryService {

    private final MonthlyAttendanceStatMapper attendanceStatMapper;
    private final MonthlyOvertimeStatMapper overtimeStatMapper;
    private final HrEmployeeMapper employeeMapper;
    private final AnnualLeaveMapper annualLeaveMapper;

    @Override
    public EmployeeAttendanceSummaryVo getMonthlySummary(String employeeNo, Integer year, Integer month) {
        // 查询员工信息
        HrEmployee employee = employeeMapper.selectOne(Wrappers.lambdaQuery(HrEmployee.class)
                .eq(HrEmployee::getEmployeeNo, employeeNo)
                .last("LIMIT 1"));

        if (employee == null) {
            return null;
        }

        // 查询月度考勤统计
        MonthlyAttendanceStat attendanceStat = attendanceStatMapper.selectOne(
            Wrappers.lambdaQuery(MonthlyAttendanceStat.class)
                .eq(MonthlyAttendanceStat::getEmployeeNo, employeeNo)
                .eq(null != year, MonthlyAttendanceStat::getYear, year)
                .eq(null != month, MonthlyAttendanceStat::getMonth, month));

        // 查询月度加班统计
        MonthlyOvertimeStat overtimeStat = overtimeStatMapper.selectOne(
            Wrappers.lambdaQuery(MonthlyOvertimeStat.class)
                .eq(MonthlyOvertimeStat::getEmployeeNo, employeeNo)
                .eq(null != year, MonthlyOvertimeStat::getYear, year)
                .eq(null != month, MonthlyOvertimeStat::getMonth, month));

        // 组装汇总信息
        EmployeeAttendanceSummaryVo summary = new EmployeeAttendanceSummaryVo();
        summary.setEmployeeNo(employeeNo);
        summary.setEmployeeName(employee.getEmployeeName());
        summary.setUserId(employee.getUserId());
        summary.setYear(year);
        summary.setMonth(month);

        if (attendanceStat != null) {
            summary.setWorkDays(attendanceStat.getWorkDays());
            summary.setActualDays(attendanceStat.getNormalDays());
            summary.setLateCount(attendanceStat.getLateCount());
            summary.setEarlyCount(attendanceStat.getEarlyCount());
            summary.setAbsenceCount(attendanceStat.getAbsenceCount());
            summary.setPersonalLeaveDays(attendanceStat.getPersonalLeaveDays());
            summary.setSickLeaveDays(attendanceStat.getSickLeaveDays());
            summary.setAnnualLeaveDays(attendanceStat.getAnnualLeaveDays());
            summary.setCompensatoryLeaveDays(attendanceStat.getCompensatoryLeaveDays());
            summary.setOtherLeaveDays(attendanceStat.getOtherLeaveDays());
            summary.setAttendanceStatus(attendanceStat.getStatus());
            summary.setExceptionReason(attendanceStat.getRemark());
        }

        if (overtimeStat != null) {
            summary.setTotalOvertimeMinutes(overtimeStat.getTotalMinutes());
            summary.setTotalOvertimeHours(
                overtimeStat.getTotalMinutes() != null ? overtimeStat.getTotalMinutes() / 60.0 : null);
            summary.setWorkdayOvertimeMinutes(overtimeStat.getWorkdayMinutes());
            summary.setWeekendOvertimeMinutes(overtimeStat.getWeekendMinutes());
            summary.setHolidayOvertimeMinutes(overtimeStat.getHolidayMinutes());
            summary.setOvertimeCount(overtimeStat.getOvertimeCount());
        }
        if(year != null){
            AnnualLeave annualLeave = annualLeaveMapper.selectOne(Wrappers.lambdaQuery(AnnualLeave.class)
                .eq(AnnualLeave::getEmployeeNo, employeeNo)
                .eq(AnnualLeave::getYear, year));
            if (annualLeave != null) {
                summary.setRemainingAnnualLeaveDays(annualLeave.getRemainingDays());
                summary.setAnnualLeaveDays(annualLeave.getUsedDays());
            }
        }

        return summary;
    }

    @Override
    public EmployeeAttendanceSummaryVo getAnnualSummary(String employeeNo, Integer year) {
        // 查询员工信息
        HrEmployee employee = employeeMapper.selectOne(
            Wrappers.lambdaQuery(HrEmployee.class)
                .eq(HrEmployee::getEmployeeNo, employeeNo)
                .last("LIMIT 1"));

        if (employee == null) {
            return null;
        }

        // 查询年度考勤统计汇总
        List<MonthlyAttendanceStat> attendanceStats = attendanceStatMapper.selectList(
            Wrappers.lambdaQuery(MonthlyAttendanceStat.class)
                .eq(MonthlyAttendanceStat::getEmployeeNo, employeeNo)
                .eq(MonthlyAttendanceStat::getYear, year));

        // 查询年度加班统计汇总
        List<MonthlyOvertimeStat> overtimeStats = overtimeStatMapper.selectList(
            Wrappers.lambdaQuery(MonthlyOvertimeStat.class)
                .eq(MonthlyOvertimeStat::getEmployeeNo, employeeNo)
                .eq(MonthlyOvertimeStat::getYear, year));

        // 组装年度汇总信息
        EmployeeAttendanceSummaryVo summary = new EmployeeAttendanceSummaryVo();
        summary.setEmployeeNo(employeeNo);
        summary.setEmployeeName(employee.getEmployeeName());
        summary.setUserId(employee.getUserId());
        summary.setYear(year);
        summary.setMonth(0); // 年度汇总

        // 汇总考勤数据
        int workDays = 0;
        int actualDays = 0;
        int lateCount = 0;
        int earlyCount = 0;
        int absenceCount = 0;
        BigDecimal personalLeaveDays = BigDecimal.ZERO;
        BigDecimal sickLeaveDays = BigDecimal.ZERO;
        BigDecimal annualLeaveDays = BigDecimal.ZERO;
        BigDecimal compensatoryLeaveDays = BigDecimal.ZERO;
        BigDecimal otherLeaveDays = BigDecimal.ZERO;

        for (MonthlyAttendanceStat stat : attendanceStats) {
            workDays += stat.getWorkDays() != null ? stat.getWorkDays() : 0;
            actualDays += stat.getNormalDays() != null ? stat.getNormalDays() : 0;
            lateCount += stat.getLateCount() != null ? stat.getLateCount() : 0;
            earlyCount += stat.getEarlyCount() != null ? stat.getEarlyCount() : 0;
            absenceCount += stat.getAbsenceCount() != null ? stat.getAbsenceCount() : 0;
            personalLeaveDays = personalLeaveDays
                .add(stat.getPersonalLeaveDays() != null ? stat.getPersonalLeaveDays() : BigDecimal.ZERO);
            sickLeaveDays = sickLeaveDays
                .add(stat.getSickLeaveDays() != null ? stat.getSickLeaveDays() : BigDecimal.ZERO);
            annualLeaveDays = annualLeaveDays
                .add(stat.getAnnualLeaveDays() != null ? stat.getAnnualLeaveDays() : BigDecimal.ZERO);
            compensatoryLeaveDays = compensatoryLeaveDays
                .add(stat.getCompensatoryLeaveDays() != null ? stat.getCompensatoryLeaveDays() : BigDecimal.ZERO);
            otherLeaveDays = otherLeaveDays
                .add(stat.getOtherLeaveDays() != null ? stat.getOtherLeaveDays() : BigDecimal.ZERO);
        }

        summary.setWorkDays(workDays);
        summary.setActualDays(actualDays);
        summary.setLateCount(lateCount);
        summary.setEarlyCount(earlyCount);
        summary.setAbsenceCount(absenceCount);
        summary.setPersonalLeaveDays(personalLeaveDays);
        summary.setSickLeaveDays(sickLeaveDays);
        summary.setAnnualLeaveDays(annualLeaveDays);
        summary.setCompensatoryLeaveDays(compensatoryLeaveDays);
        summary.setOtherLeaveDays(otherLeaveDays);

        // 汇总加班数据
        int totalOvertimeMinutes = 0;
        int workdayOvertimeMinutes = 0;
        int weekendOvertimeMinutes = 0;
        int holidayOvertimeMinutes = 0;
        int overtimeCount = 0;

        for (MonthlyOvertimeStat stat : overtimeStats) {
            totalOvertimeMinutes += stat.getTotalMinutes() != null ? stat.getTotalMinutes() : 0;
            workdayOvertimeMinutes += stat.getWorkdayMinutes() != null ? stat.getWorkdayMinutes() : 0;
            weekendOvertimeMinutes += stat.getWeekendMinutes() != null ? stat.getWeekendMinutes() : 0;
            holidayOvertimeMinutes += stat.getHolidayMinutes() != null ? stat.getHolidayMinutes() : 0;
            overtimeCount += stat.getOvertimeCount() != null ? stat.getOvertimeCount() : 0;
        }

        summary.setTotalOvertimeMinutes(totalOvertimeMinutes);
        summary.setTotalOvertimeHours(totalOvertimeMinutes > 0 ? totalOvertimeMinutes / 60.0 : null);
        summary.setWorkdayOvertimeMinutes(workdayOvertimeMinutes);
        summary.setWeekendOvertimeMinutes(weekendOvertimeMinutes);
        summary.setHolidayOvertimeMinutes(holidayOvertimeMinutes);
        summary.setOvertimeCount(overtimeCount);

        return summary;
    }

    @Override
    public List<EmployeeAttendanceSummaryVo> listSummary(String employeeNo, Integer year, Integer month) {
        List<EmployeeAttendanceSummaryVo> result = new ArrayList<>();

        if (null == year) {
            year = LocalDate.now().getYear();
            if (null == month) {
                month = LocalDate.now().getMonthValue();
            }
        }

        // 查询员工信息
        LambdaQueryWrapper<HrEmployee> employeeWrapper = Wrappers.lambdaQuery(HrEmployee.class);
        if (StringUtils.isNotBlank(employeeNo)) {
            employeeWrapper.eq(HrEmployee::getEmployeeNo, employeeNo);
        }
        List<HrEmployee> employees = employeeMapper.selectList(employeeWrapper);

        if (CollUtil.isEmpty(employees)) {
            return result;
        }

        for (HrEmployee employee : employees) {
            String empNo = employee.getEmployeeNo();
            // 构建查询条件
            LambdaQueryWrapper<MonthlyAttendanceStat> attendanceWrapper = Wrappers
                .lambdaQuery(MonthlyAttendanceStat.class)
                .eq(MonthlyAttendanceStat::getEmployeeNo, empNo)
                .eq(null != year, MonthlyAttendanceStat::getYear, year);

            if (month != null) {
                attendanceWrapper.eq(MonthlyAttendanceStat::getMonth, month);
            }

            // 查询考勤统计
            List<MonthlyAttendanceStat> attendanceStats = attendanceStatMapper.selectList(attendanceWrapper);

            // 构建加班统计查询条件
            LambdaQueryWrapper<MonthlyOvertimeStat> overtimeWrapper = Wrappers.lambdaQuery(MonthlyOvertimeStat.class)
                .eq(MonthlyOvertimeStat::getEmployeeNo, empNo)
                .eq(MonthlyOvertimeStat::getYear, year);

            if (month != null) {
                overtimeWrapper.eq(MonthlyOvertimeStat::getMonth, month);
            }

            // 查询加班统计
            List<MonthlyOvertimeStat> overtimeStats = overtimeStatMapper.selectList(overtimeWrapper);

            // 按月份合并数据
            for (MonthlyAttendanceStat attendanceStat : attendanceStats) {
                EmployeeAttendanceSummaryVo summary = new EmployeeAttendanceSummaryVo();
                summary.setEmployeeNo(empNo);
                summary.setEmployeeName(employee.getEmployeeName());
                summary.setUserId(employee.getUserId());
                summary.setYear(attendanceStat.getYear());
                summary.setMonth(attendanceStat.getMonth());

                // 设置考勤数据
                summary.setWorkDays(attendanceStat.getWorkDays());
                summary.setActualDays(attendanceStat.getNormalDays());
                summary.setLateCount(attendanceStat.getLateCount());
                summary.setEarlyCount(attendanceStat.getEarlyCount());
                summary.setAbsenceCount(attendanceStat.getAbsenceCount());
                summary.setPersonalLeaveDays(attendanceStat.getPersonalLeaveDays());
                summary.setSickLeaveDays(attendanceStat.getSickLeaveDays());
                summary.setAnnualLeaveDays(attendanceStat.getAnnualLeaveDays());
                summary.setCompensatoryLeaveDays(attendanceStat.getCompensatoryLeaveDays());
                summary.setOtherLeaveDays(attendanceStat.getOtherLeaveDays());
                summary.setAttendanceStatus(attendanceStat.getStatus());
                summary.setExceptionReason(attendanceStat.getRemark());

                // 查找对应的加班数据
                for (MonthlyOvertimeStat overtimeStat : overtimeStats) {
                    if (overtimeStat.getYear().equals(attendanceStat.getYear()) &&
                        overtimeStat.getMonth().equals(attendanceStat.getMonth())) {
                        summary.setTotalOvertimeMinutes(overtimeStat.getTotalMinutes());
                        summary.setTotalOvertimeHours(overtimeStat.getTotalMinutes() != null ? overtimeStat.getTotalMinutes() / 60.0 : null);
                        summary.setWorkdayOvertimeMinutes(overtimeStat.getWorkdayMinutes());
                        summary.setWeekendOvertimeMinutes(overtimeStat.getWeekendMinutes());
                        summary.setHolidayOvertimeMinutes(overtimeStat.getHolidayMinutes());
                        summary.setOvertimeCount(overtimeStat.getOvertimeCount());
                        break;
                    }
                }

                // 获取员工当年剩余年假天数
                if (year != null) {
                   AnnualLeave annualLeave = annualLeaveMapper.selectOne(Wrappers.lambdaQuery(AnnualLeave.class)
                                .eq(AnnualLeave::getEmployeeNo, empNo)
                                .eq(AnnualLeave::getYear, year));
                    if (annualLeave != null) {
                        summary.setRemainingAnnualLeaveDays(annualLeave.getRemainingDays());
                        summary.setAnnualLeaveDays(annualLeave.getUsedDays());
                    }
                }

                result.add(summary);
            }
        }

        return result;
    }

    @Override
    public TableDataInfo<EmployeeAttendanceSummaryVo> listSummaryPage(String employeeNo, Integer year,
                                                                      Integer month, PageQuery pageQuery) {
        // 先获取所有数据
        List<EmployeeAttendanceSummaryVo> allData = listSummary(employeeNo, year, month);

        // 根据分页参数截取数据
        int total = allData.size();
        int startIndex = (pageQuery.getPageNum() - 1) * pageQuery.getPageSize();
        int endIndex = Math.min(startIndex + pageQuery.getPageSize(), total);

        List<EmployeeAttendanceSummaryVo> pageData = new ArrayList<>();
        if (startIndex < total) {
            pageData = allData.subList(startIndex, endIndex);
        }

        return new TableDataInfo<>(pageData, total);
    }
}
